﻿using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RecordBill.Core
{

    public class DecompressZip
    {
        private static bool passwordFound = false;
        private static string correctPassword = "";
        private static object lockObject = new object();
        private static int attempts = 0;

        public static void GetExcelFile(string zipPath)
        {
            Console.WriteLine("ZIP密码暴力破解工具");
            Console.WriteLine("====================");



            if (!File.Exists(zipPath))
            {
                Console.WriteLine("文件不存在！");
                return;
            }

            var threadCount = 4; // 默认线程数


            Console.WriteLine($"开始暴力破解，使用 {threadCount} 个线程...");
            Console.WriteLine("正在尝试密码...");

            DateTime startTime = DateTime.Now;

            // 启动破解任务
            CrackPassword(zipPath, threadCount);

            if (passwordFound)
            {
                DateTime endTime = DateTime.Now;
                TimeSpan duration = endTime - startTime;

                Console.WriteLine($"\n破解成功！");
                Console.WriteLine($"正确密码: {correctPassword}");
                Console.WriteLine($"尝试次数: {attempts}");
                Console.WriteLine($"耗时: {duration.TotalSeconds:F2} 秒");

                // 解压文件
                ExtractFiles(zipPath, correctPassword);
            }
            else
            {
                Console.WriteLine("\n破解失败！未找到正确密码。");
            }

        }

        static void CrackPassword(string zipPath, int threadCount)
        {
            // 创建任务数组
            Task[] tasks = new Task[threadCount];

            // 计算每个线程要处理的密码范围
            int totalPasswords = 1000000; // 000000-999999
            int passwordsPerThread = totalPasswords / threadCount;

            for (int i = 0; i < threadCount; i++)
            {
                int start = i * passwordsPerThread;
                int end = (i == threadCount - 1) ? totalPasswords : (i + 1) * passwordsPerThread;

                tasks[i] = Task.Run(() => TryPasswordRange(zipPath, start, end));
            }

            // 显示进度
            Task progressTask = Task.Run(() => ShowProgress());

            // 等待所有任务完成
            Task.WaitAll(tasks);
            passwordFound = true; // 确保进度显示停止
            progressTask.Wait(100); // 给进度显示任务一点时间结束
        }

        static void TryPasswordRange(string zipPath, int start, int end)
        {
            for (int i = start; i < end && !passwordFound; i++)
            {
                string password = i.ToString("D6"); // 格式化为6位数字

                if (TryPassword(zipPath, password))
                {
                    lock (lockObject)
                    {
                        if (!passwordFound) // 双重检查，避免多个线程同时找到密码
                        {
                            passwordFound = true;
                            correctPassword = password;
                        }
                    }
                    return;
                }

                // 更新尝试次数
                Interlocked.Increment(ref attempts);
            }
        }
        static bool TryPassword(string zipPath, string password)
        {
            if(password=="136625")
            {
                var s = "123";
            }
            try
            {
                using (var fs = File.OpenRead(zipPath))
                {
                    var zip = new ZipFile(fs);
                    zip.Password = password;
                    if (zip.Count>0)
                    {
                        var entry = zip[0];
                        if(entry.CanDecompress)
                        {

                            var s = zip.GetInputStream(entry);
                            s.Close();
                        }
                        return true;
                    }
                }
                return false;
            }
            catch (InvalidDataException)
            {
                // 密码错误
                return false;
            }
            catch (Exception)
            {
                // 其他异常，可能是文件损坏等
                return false;
            }
        }
        //static bool TryPassword(string zipPath, string password)
        //{
        //    try
        //    {
        //        using (ZipArchive archive = ZipFile.Open(zipPath, ZipArchiveMode.Read, Encoding.UTF8, password))
        //        {
                  
                 
        //            // 尝试访问第一个条目来验证密码
        //            foreach (var entry in archive.Entries)
        //            {
        //                try
        //                {
        //                    // 尝试解压条目到内存流来验证密码
        //                    using (var stream = entry.Open())
        //                    using (var memoryStream = new MemoryStream())
        //                    {
        //                        stream.CopyTo(memoryStream);
        //                    }
        //                    return true; // 如果没有异常，密码正确
        //                }
        //                catch (Exception)
        //                {
        //                    // 密码错误，继续尝试下一个密码
        //                    return false;
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        // 处理其他异常
        //        if (ex is InvalidDataException || ex is NotSupportedException)
        //        {
        //            return false; // 密码错误
        //        }
        //        // 其他异常可能需要处理
        //    }

        //    return false;
        //}

        static void ShowProgress()
        {
            int lastAttempts = 0;
            DateTime lastTime = DateTime.Now;

            while (!passwordFound)
            {
                Thread.Sleep(1000); // 每秒更新一次

                int currentAttempts = attempts;
                DateTime currentTime = DateTime.Now;

                double attemptsPerSecond = (currentAttempts - lastAttempts) / (currentTime - lastTime).TotalSeconds;

                Console.Write($"\r尝试次数: {currentAttempts} | 速度: {attemptsPerSecond:F1} 次/秒 | 当前时间: {DateTime.Now:HH:mm:ss}");

                lastAttempts = currentAttempts;
                lastTime = currentTime;
            }

            Console.WriteLine(); // 换行
        }

        static void ExtractFiles(string zipPath, string password)
        {
            // 创建解压目录
            string extractDir = Path.Combine(Path.GetDirectoryName(zipPath),
                Path.GetFileNameWithoutExtension(zipPath) + "_extracted");

            if (!Directory.Exists(extractDir))
                Directory.CreateDirectory(extractDir);
            try
            {
                using (FileStream fileStreamIn = new FileStream(zipPath, FileMode.Open, FileAccess.Read))
                {
                    using (ZipInputStream zipInStream = new ZipInputStream(fileStreamIn))
                    {
                        zipInStream.Password = password;
                        ZipEntry entry = zipInStream.GetNextEntry();
                        do
                        {
                            using (FileStream fileStreamOut = new FileStream(extractDir + @"\" + entry.Name, FileMode.Create, FileAccess.Write))
                            {

                                int size = 2048;
                                byte[] buffer = new byte[2048];
                                do
                                {
                                    size = zipInStream.Read(buffer, 0, buffer.Length);
                                    fileStreamOut.Write(buffer, 0, size);
                                } while (size > 0);
                            }
                        } while ((entry = zipInStream.GetNextEntry()) != null);
                    }
                }
                Console.WriteLine($"\n开始解压文件...");


                    Console.WriteLine($"\n解压完成！");
                   
                    Console.WriteLine($"文件已解压到: {Directory.GetCurrentDirectory()}");
                
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解压过程中出错: {ex.Message}");
            }
        }

        static bool IsExcelFile(string fileName)
        {
            string extension = Path.GetExtension(fileName).ToLower();
            return extension == ".xlsx" || extension == ".xls" || extension == ".xlsm";
        }
    }
}
